#include "widget.h"

Widget::Widget(QWidget *parent) :QWidget(parent)
  ,borderWidth(1)
  ,titleHeight(30)
  ,hasBorder(true)
  ,hasTitleBar(true)
  ,hasStatusBar(true)
  ,centerWidget(new QWidget(this))
  ,isLeftPressDown(false)
  ,areaDrag(false)
  ,titleClicked(false)
{

}

void Widget::mousePressEvent(QMouseEvent *event)
{
    switch(event->button()) {
    case Qt::LeftButton:
        isLeftPressDown = true;
        if(dir != NONE) {
            this->mouseGrabber();
        } else {
            dragPosition = event->globalPos()-pos();
        }
        if (areaDrag){
            QWidget::mousePressEvent(event);
        }
        if (event->pos().y()<titleHeight+3*borderWidth){
            titleClicked=true;
        }
        break;
    default:
        break;
    }
}

void Widget::mouseMoveEvent(QMouseEvent *event)
{
    QPoint gloPoint = QCursor::pos();
    QRect rect = this->rect();
    QPoint tl = mapToGlobal(rect.topLeft());
    QPoint rb = mapToGlobal(rect.bottomRight());
    if (isHasBorder()){
        if(!isLeftPressDown) {
            this->region(gloPoint);
        } else {
            if(isMaximized() && gloPoint.y()<titleHeight){
                showNormal();
                isLeftPressDown = false;
                return;
            }
            if(dir != NONE) {
                QRect rMove(tl, rb);
                switch(dir) {
                case LEFT:
                    if(rb.x() - gloPoint.x() <= this->minimumWidth()){
                        rMove.setX(tl.x());
                    } else{
                        rMove.setX(gloPoint.x());
                    }
                    break;
                case RIGHT:
                    rMove.setWidth(gloPoint.x() - tl.x());
                    break;
                case UP:
                    if(rb.y() - gloPoint.y() <= this->minimumHeight()){
                        rMove.setY(tl.y());
                    }else{
                        rMove.setY(gloPoint.y());
                    }
                    break;
                case DOWN:
                    rMove.setHeight(gloPoint.y() - tl.y());
                    break;
                case LEFTTOP:
                    if(rb.x() - gloPoint.x() <= this->minimumWidth()){
                        rMove.setX(tl.x());
                    }else{
                        rMove.setX(gloPoint.x());
                    }
                    if(rb.y() - gloPoint.y() <= this->minimumHeight()){
                        rMove.setY(tl.y());
                    }else{
                        rMove.setY(gloPoint.y());
                    }
                    break;
                case RIGHTTOP:
                    rMove.setWidth(gloPoint.x() - tl.x());
                    rMove.setY(gloPoint.y());
                    break;
                case LEFTBOTTOM:
                    rMove.setX(gloPoint.x());
                    rMove.setHeight(gloPoint.y() - tl.y());
                    break;
                case RIGHTBOTTOM:
                    rMove.setWidth(gloPoint.x() - tl.x());
                    rMove.setHeight(gloPoint.y() - tl.y());
                    break;
                default:
                    break;
                }
                this->setGeometry(rMove);
            }else if (isLeftPressDown&&titleClicked){
                move(QCursor().pos()-dragPosition);
                return;
            }else if (areaDrag){
                move(QCursor().pos() - dragPosition );
                dragPosition = QCursor::pos()-pos();
                setCursor(Qt::ClosedHandCursor);
                QWidget::mouseMoveEvent(event);
                return;
            }
        }
    }
    QWidget::mouseMoveEvent(event);
}

void Widget::mouseReleaseEvent(QMouseEvent *e)
{
    if(e->button() == Qt::LeftButton) {
        isLeftPressDown = false;
        titleClicked=false;
        if(dir != NONE) {
            this->releaseMouse();
            this->setCursor(QCursor(Qt::ArrowCursor));
            emit sizeChanged(this->size());
        }
    }
}

void Widget::paintEvent(QPaintEvent *e)
{
    _initialze();
    paintFrame();
    QWidget::paintEvent(e);
}

void Widget::leaveEvent(QEvent *)
{
    isLeftPressDown = false;
}

void Widget::mouseDoubleClickEvent(QMouseEvent *e)
{
    if (e->button()==Qt::LeftButton){
        if (e->pos().y()<titleHeight){
            if (isMaximized()){
                showNormal();
            }else{
                showMaximized();
            }
        }
    }
}

void Widget::drawEverything(QPainter *)
{

}

/**
 * @brief paintFrame        画边框
 */
void Widget::paintFrame()
{
    painter->begin(this);
    //画标题栏
    if (isHasTitleBar()){
        titleWidget->show();
        painter->setPen(titleWidget->getTitleColor());
        painter->setBrush(titleWidget->getTitleColor());
        painter->drawRect(borderWidth,borderWidth, width()+2*borderWidth, titleHeight);
    }else {
        painter->eraseRect(borderWidth,borderWidth, width()+2*borderWidth, titleHeight);
    }
    //画边框
    if (isHasBorder()){
        painter->setPen(borderPen);
        painter->setBrush(QBrush(borderPen.color()));
        painter->drawRect(0,0,borderWidth,height());
        painter->drawRect(width()-borderWidth,0,borderWidth,height());
        painter->drawRect(0,0,width(),borderWidth);
        painter->drawRect(0,height()-borderWidth,width(),borderWidth);
    }else{
        painter->eraseRect(0,0,borderWidth,height());
        painter->eraseRect(width()-borderWidth,0,borderWidth,height());
        painter->eraseRect(0,0,width(),borderWidth);
        painter->eraseRect(0,height()-borderWidth,width(),borderWidth);
    }
    drawEverything(painter);
    painter->end();
}

/**
 * @brief init      初始化
 */
bool inited = false;
void Widget::_initialze()
{
    if (inited){
        return;
    }
    inited = true;
    //去掉边框
    setWindowFlags(Qt::FramelessWindowHint);
    setMouseTracking(true);
    setWindowOpacity(0.8);
    painter = new QPainter(this);
    centerLayout = new QGridLayout;
    centerLayout->setContentsMargins(1,1,1,1);
    centerLayout->setMargin(2);
    //边框默认为灰色半透明
    setBorderColor(QColor(50,50,50,50));
    layout = new QVBoxLayout();
    layout->setContentsMargins(1,1,1,1);
    widget = new QWidget(this);
    widget->setMouseTracking(true);
    widget->setLayout(centerLayout);
    centerWidget->setMouseTracking(true);
    centerLayout->addWidget(centerWidget);
    titleWidget = new TitleWidget(titleHeight,Qt::lightGray,this);
    layout->addWidget(titleWidget);
    layout->addWidget(widget);
    layout->setStretch(0,1);
    layout->setStretch(1,100);
    layout->setSpacing(0);
    layout->setMargin(1);
    textPen=borderPen;
    setLayout(layout);
    this->dir = NONE;
    setTitle("新窗口");
    resize(500,400);
}

QColor Widget::getBackGroundColor() const
{
    return backGroundColor;
}

/**
 * @brief getTitleTextColor     标题颜色
 * @return
 */
QColor Widget::getTitleTextColor()
{
    _initialze();
    return titleTextColor;
}

void Widget::setTitleTextColor(const QColor &value)
{
    _initialze();
    titleTextColor = value;
    titleWidget->title->setStyleSheet(QString("color: rgb(%1,%2,%3,%4)").arg(value.red()).arg(value.green())
                                      .arg(value.blue()).arg(value.alpha()));
}

/**
 * @brief addWidget     添加窗口
 * @param x
 * @param y
 * @param widget
 */
void Widget::addWidget(int x, int y, QWidget *widget)
{
    _initialze();
    if (centerWidget && widget){
        widget->setParent(centerWidget);
        widget->move(x,y);
        widget->show();
    }
}

void Widget::emitSizeChangeSignal()
{
    emit sizeChanged(size());
}

/**
 * @brief isAreaDrag                区域可拖动
 * @return
 */
bool Widget::isAreaDrag()
{
    return areaDrag;
}

void Widget::setAreaDrag(bool value)
{
    areaDrag = value;
}

/**
 * @brief getTitleWidget            获取标题窗口
 */
QWidget* Widget::getTitleWidget()
{
    _initialze();
    return titleWidget;
}

/**
 * @brief getCenterWidget       获取中央窗口
 * @return
 */
QWidget *Widget::getCentreWidget()
{
    _initialze();
    return centerWidget;
}

void Widget::setCentreWidget(QWidget *value)
{
    _initialze();
    if (value != nullptr){
        if (centerLayout->count()){
            centerLayout->removeWidget(centerWidget);
            delete centerWidget;
            centerWidget = nullptr;
        }
        value->setParent(this);
        centerLayout->addWidget(value);
        value->setStyleSheet(strBackGroundColor);
        centerWidget = value;
    }
}

/**
 * @brief getTitle              获取标题
 * @return
 */
QString Widget::getTitle()
{
    _initialze();
    return titleWidget->getTitle();
}
void Widget::setTitle(const QString &title)
{
    _initialze();
    titleWidget->setTitle(title);
    QWidget::setWindowTitle(title);
}

/**
 * @brief getIcon               获取图标
 * @return
 */
QString Widget::getIcon()
{
    _initialze();
    return titleWidget->getIcon();
}

void Widget::setIcon(const QString &fileName)
{
    _initialze();
    titleWidget->setIcon(fileName);
}

/**
 * @brief getTitleLable  操作标题
 * @return
 */
QLabel *Widget::getTitleLable()
{
    _initialze();
    return titleWidget->getTitleLabel();
}

QLabel *Widget::getIconLable()
{
    _initialze();
    return titleWidget->getIconLabel();
}

/**
 * @brief setBackgroundColor        设置背景颜色
 * @param color
 */
void Widget::setBackgroundColor(const QColor &color)
{
    _initialze();
    QPalette palette(QPalette::Background,color);
    setPalette(palette);
    if (centerWidget){
        QString col =  QString("background: rgba(%1,%2,%3,%4)").arg(color.red()).arg(color.green()).arg(color.blue()).arg(1/255.0*color.alpha());
        centerWidget->setStyleSheet(col);
        strBackGroundColor = col;
    }
    backGroundColor= color;
}

/**
 * @brief getPen            画笔设置
 * @return
 */
QPen Widget::getBorderPen()
{
    _initialze();
    return borderPen;
}

void Widget::setBorderColor(const QColor &value)
{
    _initialze();
    borderPen.setColor(value);
}

void Widget::setButtonShow(const BUTTON &button, bool show)
{
    _initialze();
    switch(button){
    case MIN:
        titleWidget->minButton->setVisible(show);
        return;
    case MAX:
        titleWidget->maxButton->setVisible(show);
        return;
    case CLOSE:
        titleWidget->closeButton->setVisible(show);
        return;
    default:
        return;
    }
}

/**
 * @brief getButton     获取自带button
 * @param button
 * @return
 */
QPushButton *Widget::getButton(const BUTTON &button)
{
    _initialze();
    switch(button){
    case MIN:
        return titleWidget->minButton;
    case MAX:
        return titleWidget->maxButton;

    case CLOSE:
        return titleWidget->closeButton;
    default:
        return nullptr;
    }
}

/**
 * @brief setButtonStyle        设置Button风格
 * @param button
 * @param style
 */
void Widget::setButtonStyle(const BUTTON &button, const QString &style)
{
    _initialze();
    switch(button){
    case MIN:
        titleWidget->minButton->setStyleSheet(style);
        return;
    case MAX:
        titleWidget->maxButton->setStyleSheet(style);
        return;
    case CLOSE:
        titleWidget->closeButton->setStyleSheet(style);
        return;
    default:
        return;
    }
}

/**
 * @brief hasTitleBar       有标题栏
 * @return
 */
bool Widget::isHasTitleBar()
{
    return hasTitleBar;
}

void Widget::setHasTitleBar(bool value)
{
    _initialze();
    hasTitleBar = value;
    titleWidget->setVisible(value);
}

/**
 * @brief setTitleColor 设置标题栏颜色
 * @param color
 */
void Widget::setTitleColor(const QColor &color)
{
    _initialze();
    titleWidget->setTitleColor(color);
}

/**
 * @brief getLayout     获取layout
 * @return
 */
QVBoxLayout *Widget::getLayout()
{
    _initialze();
    return layout;
}

/**
 * @brief hasBorder     有边框
 * @return
 */
bool Widget::isHasBorder()
{
    return hasBorder;
}

void Widget::setHasBorder(bool value)
{
    _initialze();
    hasBorder = value;
}


/**
 * @brief getTitleHeight        标题栏高度
 */
unsigned Widget::getTitleHeight()
{
    return titleHeight;
}

void Widget::setTitleHeight(const unsigned &value)
{
    _initialze();
    titleHeight = value;
    titleWidget->setHeight(titleHeight);
}

/**
 * @brief getBorderWidth        边框宽度
 */
unsigned Widget::getBorderWidth()
{
    return borderWidth;
}

void Widget::setBorderWidth(const unsigned &value)
{
    _initialze();
    borderWidth = value;
    layout->setMargin(value);
}

/**
 * @brief region            获取区域
 * @param cursorGlobalPoint
 */
void Widget::region(const QPoint &cursorGlobalPoint)
{
    QRect rect = this->rect();
    QPoint tl = mapToGlobal(rect.topLeft());
    QPoint rb = mapToGlobal(rect.bottomRight());

    int x = cursorGlobalPoint.x();
    int y = cursorGlobalPoint.y();

    if(((tl.x()+borderWidth)>=x) && (tl.x()<=x) && ((tl.y()+borderWidth)>=y) && (tl.y()<= y)) {
        // 左上角
        dir = LEFTTOP;
        this->setCursor(QCursor(Qt::SizeFDiagCursor));  // 设置鼠标形状
    } else if(x >= rb.x() - borderWidth && x <= rb.x() && y >= rb.y() - borderWidth && y <= rb.y()) {
        // 右下角
        dir = RIGHTBOTTOM;
        this->setCursor(QCursor(Qt::SizeFDiagCursor));
    } else if(x <= tl.x() + borderWidth && x >= tl.x() && y >= rb.y() - borderWidth && y <= rb.y()) {
        //左下角
        dir = LEFTBOTTOM;
        this->setCursor(QCursor(Qt::SizeBDiagCursor));
    } else if(x <= rb.x() && x >= rb.x() - borderWidth && y >= tl.y() && y <= tl.y() + borderWidth) {
        // 右上角
        dir = RIGHTTOP;
        this->setCursor(QCursor(Qt::SizeBDiagCursor));
    } else if(x <= tl.x() + borderWidth && x >= tl.x()) {
        // 左边
        dir = LEFT;
        this->setCursor(QCursor(Qt::SizeHorCursor));
    } else if( x <= rb.x() && x >= rb.x() - borderWidth) {
        // 右边
        dir = RIGHT;
        this->setCursor(QCursor(Qt::SizeHorCursor));
    }else if(y >= tl.y() && y <= tl.y() + borderWidth){
        // 上边
        dir = UP;
        this->setCursor(QCursor(Qt::SizeVerCursor));
    } else if(y <= rb.y() && (int)y >= rb.y() - borderWidth) {
        // 下边
        dir = DOWN;
        this->setCursor(QCursor(Qt::SizeVerCursor));
    }else {
        // 默认
        dir = NONE;
        this->setCursor(QCursor(Qt::ArrowCursor));
    }
}

TitleWidget::TitleWidget(int height ,QColor titleColor, Widget *parent) : QWidget(parent),parent(parent)
{
    this->height = height;
    this->titleColor = titleColor;
    init();
}


void TitleWidget::init()
{
    minButton = new QPushButton("-",this);
    connect(minButton,&QPushButton::clicked,[this](){parent->showMinimized();});
    minButton->setStyleSheet(QString("QPushButton{border-radius: 10px; background-color: rgba(236,64,60,1); } QPushButton:hover{ \
                          border-radius: 10px;background-color:rgba(220,50,50,1)}QPushButton:pressed{border-radius: 10px;background-color:rgba(210,40,40,1)}"));
    maxButton = new QPushButton("□",this);
    connect(maxButton, &QPushButton::clicked,[this](){parent->isMaximized()?parent->showNormal():parent->showMaximized();parent->emitSizeChangeSignal();});
    maxButton->setStyleSheet(QString("QPushButton{border-radius: 10px; background-color: rgba(156,196,1,1); } QPushButton:hover{ \
                          border-radius: 10px;background-color:rgba(140,180,0,1)}QPushButton:pressed{border-radius: 10px;background-color:green}"));
    closeButton = new QPushButton("×",this);
    connect(closeButton, &QPushButton::clicked,[this](){
       QPropertyAnimation animation(parent,"windowOpacity");
       animation.setDuration(100);
       animation.setStartValue(0.8);
       animation.setEndValue(0);
       animation.start();
       QEventLoop loop;
       connect(&animation,SIGNAL(finished()),&loop,SLOT(quit()));
       loop.exec();
       parent->close();
    });
    closeButton->setStyleSheet(QString("QPushButton{border-radius: 10px; background-color: rgba(255,160,2,1); } QPushButton:hover{ \
                          border-radius: 10px;background-color:rgba(245,150,0,1)}QPushButton:pressed{border-radius: 10px;background-color:rgba(225,130,0,1)}"));
    title = new QLabel(this);
    title->setSizePolicy(QSizePolicy::Minimum,QSizePolicy::Preferred);
    title->setText("");
    icon = new QLabel(this);
    icon->setScaledContents(true);
    icon->setFixedSize(24,22);
    icon->setText("");
    minButton->setFixedSize(20,20);
    maxButton->setFixedSize(20,20);
    closeButton->setFixedSize(20,20);
    btnLayout=new QHBoxLayout;
    btnLayout->setContentsMargins(0,0,0,0);
    btnLayout->addWidget(minButton);
    btnLayout->addWidget(maxButton);
    btnLayout->addWidget(closeButton);
    btnLayoutH = new QHBoxLayout;
    btnLayoutH->setContentsMargins(6,0,6,0);
    icon->hide();
    title->hide();
    btnLayoutH->addWidget(icon);
    btnLayoutH->addWidget(title);
    btnLayoutH->addItem(new QSpacerItem(40, 20, QSizePolicy::Expanding, QSizePolicy::Expanding));
    btnLayoutH->addLayout(btnLayout);
    setLayout(btnLayoutH);
    painter = new QPainter(this);
    titleColor = QColor(10,141,169);
    setMouseTracking(true);
}

void TitleWidget::paintEvent(QPaintEvent *)
{   
    setFixedHeight(height);
    painter->begin(this);
    painter->setPen(QPen(titleColor));
    painter->setBrush(QBrush(titleColor));
    painter->drawRect(rect());
    painter->end();
}

void TitleWidget::setHeight(int height)
{
    this->height = height;
    repaint();
    setIcon(strIcon);
}

void TitleWidget::setTitle(const QString &title)
{
    this->title->setText(title);
    if (title.isEmpty()){
        this->title->hide();
    }else{
        this->title->show();
    }
    this->strTitle = title;
}

void TitleWidget::setIcon(const QString &fileName)
{
    if (QFile::exists(fileName)){
        icon->setPixmap(QPixmap(fileName));
        icon->show();
    }else{
        icon->clear();
        icon->hide();
    }
    strIcon = fileName;
}

QString TitleWidget::getTitle()
{
    return this->strTitle;
}

QString TitleWidget::getIcon()
{
    return strIcon;
}

QLabel *TitleWidget::getTitleLabel()
{
    return title;
}

QLabel *TitleWidget::getIconLabel()
{
    return icon;
}

QColor TitleWidget::getTitleColor()
{
    return titleColor;
}

void TitleWidget::setTitleColor(const QColor &value)
{
    titleColor = value;
    repaint();
}
